#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import json
import logging
import traceback
from store.store import BasicStore
from public.util import is_none


class MdbStore(BasicStore):
    def __init__(self, config):
        self.mdb = config['mdb']

    def table_exists(self, table_name):
        sql = 'show tables;'
        rows = self.mdb.query(sql)
        tables = []
        for row in rows:
            tables.append(row[0])
        if table_name in tables:
            return True
        return False

    def commit(self):
        self.mdb.commit()

    def close(self):
        self.mdb.close()


# 存mysql table
class TableStore(MdbStore):
    def __init__(self, config):
        super(TableStore, self).__init__(config)
        # 表名
        self.table = config['table']
        # 列 和 列定义 字典
        self.column_dic = config['column_dic']
        self.columns = list(self.column_dic.keys())
        # 唯一索引列
        self.uniq_idx_fields = config['uniq_idx_fields']
        # 常规索引名称和索引列 字典
        self.idx_dic = config.get('idx_dic', {})
        # on duplicate key 更新列
        self.update_fields = config.get('update_fields', [])
        # 和列一一对应的数据域， 默认和列一样
        self.fields = config.get('fields', self.columns)
        # 需要json dumps处理的列
        self.dump_fields = config.get('dump_fields', [])
        # 需要 text无defalut值，值可为空
        self.text_fields = config.get('text_fields', [])

        if not self.table_exists(self.table):
            self.check_create(self.table)
            self.commit()

    # 检查表，如果没有则创建表
    def check_create(self, table):
        sql_head = 'create table IF NOT EXISTS `{0}`(`id` int(11) NOT NULL AUTO_INCREMENT, '.format(table)
        sql_body = ''
        for field in self.column_dic.keys():
            sql_body += '`{0}` {1}, '.format(field, self.column_dic[field])
        if 'update_time' in self.column_dic.keys():
            sql_foot = 'PRIMARY KEY (`id`), '
        else:
            sql_foot = '''`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP 
                            ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), '''
        sql_uniq = 'UNIQUE KEY `{0}_uniq_idx` (`{1}`) '.format(table, '`, `'.join(self.uniq_idx_fields))
        sql_idx = ','
        for k, v in self.idx_dic.items():
            sql_idx += 'KEY `{0}` (`{1}`), '.format(k, '`, `'.join(v))
        sql_end = ') ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;'
        sql = sql_head + sql_body + sql_foot + sql_uniq + sql_idx.rstrip(', ') + sql_end
        self.mdb.execute(sql)

    # 往表中写数据, key为表名，value为表字段值字典，字典的keys和self.fields字段一致
    def set(self, key, data, extra=None):
        if is_none(key) is False and key != self.table:
            # 这个用法有些奇怪，写入表名成和初始化表名称不一致的时候，创建一张新表
            # 不应该支持的，让人困惑
            table = key
            if not self.table_exists(table):
                self.check_create(table)
        else:
            table = self.table
        value = []
        try:
            act_columns = []
            i = -1
            for field in self.fields:
                i += 1
                if field not in data:
                    if field in self.text_fields:
                        value.append('')
                    else:
                        continue
                elif is_none(data[field]):
                    if field in self.text_fields:
                        value.append('')
                    else:
                        continue
                elif field in self.dump_fields:
                    value.append(json.dumps(data[field]).encode('utf-8').decode('unicode_escape'))
                else:
                    value.append(data[field])
                act_columns.append(self.columns[i])
            sql_insert = 'insert into `{0}`(`{1}`) values {2} '.format(
                table, '`, `'.join(act_columns), tuple(value)
            )
            if len(self.update_fields) > 0:
                sql_update = ''
                for field in self.update_fields:
                    if field not in data:
                        continue
                    if is_none(data[field]):
                        continue
                    if field in self.dump_fields:
                        sql_update += "`{0}`='{1}', ".format(field, json.dumps(data[field]).encode('utf-8').decode('unicode_escape'))
                    elif isinstance(data[field], str):
                        sql_update += "`{0}`='{1}', ".format(field, data[field])
                    else:
                        sql_update += '`{0}`={1}, '.format(field, data[field])
                sql_update = sql_update.rstrip(', ')
                if len(sql_update) > 0:
                    sql = sql_insert + ' ON DUPLICATE KEY UPDATE ' + sql_update + ';'
                else:
                    sql = sql_insert + ';'
            else:
                sql = sql_insert + ';'
            status_code = self.mdb.execute(sql)
            if status_code == 0:
                return True
        except Exception as e:
            logging.error(e)
            logging.error(traceback.format_exc())
        return False
